package com.arpa.wms.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.StrUtil;
import com.arpa.core.web.MediaTypes;
import com.arpa.core.web.Result;
import com.arpa.ntocc.common.common.Page;
import com.arpa.ntocc.common.common.cache.PartyCache;
import com.arpa.ntocc.common.common.cache.PartyCacheDO;
import com.arpa.ntocc.common.common.cache.ShipmentCache;
import com.arpa.ntocc.common.common.constant.StrConsts;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.ShipmentWarehouseValidate;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.ntocc.common.domain.entity.Shipment;
import com.arpa.ntocc.common.domain.enums.PartyTypeEnum;
import com.arpa.ntocc.common.domain.vo.ShipmentVO;
import com.arpa.ntocc.common.security.annotation.NeedLogin;
import com.arpa.ntocc.common.service.IShipmentService;
import com.arpa.wms.cache.WarehouseCache;
import com.arpa.wms.domain.consts.CommonConst;
import com.arpa.wms.domain.consts.NumConst;
import com.arpa.wms.domain.dto.WarehouseShipmentDTO;
import com.arpa.wms.domain.entity.InventoryStatus;
import com.arpa.wms.domain.entity.WarehouseCollection;
import com.arpa.wms.domain.entity.WarehouseShipment;
import com.arpa.wms.domain.enums.StatusEnum;
import com.arpa.wms.domain.vo.WarehouseShipmentVO;
import com.arpa.wms.domain.vo.WarehouseVO;
import com.arpa.wms.service.IGoodsUnitService;
import com.arpa.wms.service.IInventoryStatusService;
import com.arpa.wms.service.IWarehouseShipmentService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.*;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * <p>
 * 仓库货主绑定关系 Controller
 * </p>
 *
 * @author LEO
 * @since 2020-08-03
 */
@Api(tags = "仓库货主绑定关系")
@RestController
@RequestMapping(value = "/warehouseShipment", produces = "application/json;charset=UTF-8")
@Log4j2
public class WarehouseShipmentController {

    @Autowired
    private IWarehouseShipmentService iWarehouseShipmentService;

    @Autowired
    private PartyCache partyCache;

    @Autowired
    private WarehouseCache warehouseCache;
    @Autowired
    private ShipmentCache shipmentCache;
    @Autowired
    private IGoodsUnitService goodsUnitService;
    @Autowired
    private IInventoryStatusService inventoryStatusService;
    @Autowired
    private IShipmentService iShipmentService;


    /**
     * 获取 仓库 列表
     *
     * @param warehouseShipmentDTO
     * @param request
     * @return
     */
    @ApiOperation(value = "获取仓库货主绑定关系列表", notes = "获取仓库货主绑定关系列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = WarehouseShipmentVO.class))
    @NeedLogin
    @GetMapping()
    public Result list(WarehouseShipmentDTO warehouseShipmentDTO, HttpServletRequest request) {
        try {
            warehouseShipmentDTO.setGroupCode(UserUtil.getBranchCode());
            WarehouseShipmentVO warehouseVOSom = iWarehouseShipmentService.queryListSum(warehouseShipmentDTO);
            List<WarehouseShipmentVO> warehouseVOList = iWarehouseShipmentService.queryList(warehouseShipmentDTO);
            Page returnPage = new Page(warehouseShipmentDTO.getPageNum(), warehouseShipmentDTO.getPageSize());
            returnPage.setRecords(warehouseVOList);
            returnPage.setTotal(warehouseVOSom.getTotal());
            returnPage.setSumObject(warehouseVOSom);
            return Result.ok().data(returnPage);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 获取仓库可关联货主列表
     *
     * @param warehouseShipmentDTO
     * @param request
     * @return
     */
    @ApiOperation(value = "获取仓库可关联货主列表", notes = "获取仓库可关联货主列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = ShipmentVO.class))
    @NeedLogin
    @GetMapping(value = "shipments")
    public Result shipments(WarehouseShipmentDTO warehouseShipmentDTO, HttpServletRequest request) {
        try {
            /*
            固定当前登录仓库
            warehouseShipmentDTO.setWarehouseCode(UserUtil.getLoginWarehouseCodeOrShipmentCode());
            */
            warehouseShipmentDTO.setGroupCode(UserUtil.getBranchCode());
            ShipmentVO shipmentVOSum = iWarehouseShipmentService.queryShipmentListSum(warehouseShipmentDTO);
            List<ShipmentVO> shipmentVOList = iWarehouseShipmentService.queryShipmentList(warehouseShipmentDTO);


            Page returnPage = new Page(warehouseShipmentDTO.getPageNum(), warehouseShipmentDTO.getPageSize());
            returnPage.setRecords(shipmentVOList);
            returnPage.setTotal(shipmentVOSum.getTotal());
            returnPage.setSumObject(shipmentVOSum);
            return Result.ok().data(returnPage);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }


    /**
     * 仓库货主绑定
     *
     * @param codes
     * @param request
     * @return
     */
    @ApiOperation(value = "仓库货主绑定", notes = "仓库货主绑定")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000")
    })
    @NeedLogin
    @PostMapping(value = "choose")
    public Result choose(@RequestParam List<String> codes, @RequestParam List<Integer> useOms, @RequestParam String warehouseCode, HttpServletRequest request) {
        iWarehouseShipmentService.saveChoose(codes, useOms, warehouseCode);
        return Result.ok("仓库货主绑定成功");
    }


    /**
     * 删除 仓库
     *
     * @param code
     * @param request
     * @return
     */
    @ApiOperation(value = "单条删除 仓库 ", notes = "删除 仓库 ", produces = MediaTypes.JSON_UTF_8)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "deviceId", value = "设备id", paramType = "header", dataType = "string", defaultValue = "0000000000"),
            @ApiImplicitParam(name = "code", value = "仓库code", paramType = "path", dataType = "String")
    })
    @NeedLogin
    @DeleteMapping(value = "/{code}")
    public Result delete(@PathVariable String code, HttpServletRequest request) {
        try {
            iWarehouseShipmentService.deleteByCode(code);
            return Result.ok("删除成功");
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 查询仓库数据，主要用于wms，过滤了“启用库位管理”为“关闭”状态的仓库
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "创建单据查询仓库列表数据", notes = "创建收货、发货等单据时获取登录用户所属机构启用并开启库位管理的仓库信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "shipmentCode", value = "货主code", dataType = "String"),
            @ApiImplicitParam(name = "warehouseName", value = "仓库名称", dataType = "String")
    })
    @NeedLogin
    @GetMapping(value = "chooseWarehouseData")
    public Result chooseWarehouseData(@RequestParam(value = "shipmentCode", defaultValue = "") String shipmentCode,
                                      @RequestParam(value = "warehouseName", defaultValue = "") String warehouseName,
                                      HttpServletRequest request) {
        try {
            String groupCode = UserUtil.getBranchCode();
            // 获取所有仓库缓存
            List<Map<String, Object>> warehouseList = warehouseCache.getAllByGroupCode(groupCode);
            //过滤登录用户所属机构启用并开启库位管理的仓库信息
            List<WarehouseVO> warehouseVOS = warehouseList.stream()
                    .map(m -> BeanUtil.mapToBean(m, WarehouseVO.class, false))
                    .filter(w -> StrUtil.equals(w.getStatus(), StatusEnum.ACTIVE.getValue()) && w.getLocationManagement() == 1 &&
                            StrUtil.equals(w.getGroupCode(), groupCode))
                    .collect(Collectors.toList());


            if (StrUtil.isNotBlank(shipmentCode)) {
                // 获取货主-仓库关联关系
                List<WarehouseShipment> warehouseShipments = iWarehouseShipmentService.list(new QueryWrapper<WarehouseShipment>().lambda()
                        .eq(WarehouseShipment::getShipmentCode, shipmentCode));
                if (IterUtil.isNotEmpty(warehouseShipments)) {
                    Map<String, WarehouseShipment> whCode = warehouseShipments.stream()
                            .collect(Collectors.toMap(WarehouseShipment::getWarehouseCode, a -> a));
                    //过滤登录用户所属机构启用并开启库位管理的仓库信息
                    List<WarehouseVO> data = warehouseVOS.stream()
                            .filter(m -> whCode.containsKey(m.getCode()))
                            .collect(Collectors.toList());
                    return Result.ok().data(data);
                }
            }


            return Result.ok().data(warehouseVOS);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * OMS查询仓库数据， 没有过滤“启用库位管理”为“关闭”状态的仓，查询所有可用仓库
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "OMS创建单据查询仓库列表数据", notes = "创建收货、发货等单据时获取登录用户所属机构启用并开启库位管理的仓库信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "shipmentCode", value = "货主code", dataType = "String"),
            @ApiImplicitParam(name = "warehouseName", value = "仓库名称", dataType = "String")
    })
    @NeedLogin
    @GetMapping(value = "chooseOmsWarehouseData")
    public Result chooseOmsWarehouseData(@RequestParam(value = "shipmentCode", defaultValue = "") String shipmentCode,
                                         @RequestParam(value = "warehouseName", defaultValue = "") String warehouseName,
                                         HttpServletRequest request) {
        try {
            List<String> warehouseCodes = UserUtil.getShipmentAuthorizeWarehouseCodes();
            assert warehouseCodes != null;
            List<Map<String, Object>> warehouseVOS = warehouseCodes.stream().map(s -> warehouseCache.get(s)).collect(Collectors.toList());

            return Result.ok().data(warehouseVOS);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 查询货主数据
     * TODO 根据用户授权获取货主信息
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "获取仓库绑定的货主列表数据", notes = "创建收货、发货等单据时根据所选仓库获取该仓库绑定的货主信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "warehouseCode", value = "仓库code", dataType = "String"),
            @ApiImplicitParam(name = "shipmentName", value = "货主名称", dataType = "String")
    })
    @NeedLogin
    @GetMapping(value = "chooseShipmentData")
    public Result chooseShipmentData(@RequestParam(value = "warehouseCode", defaultValue = "") String warehouseCode,
                                     @RequestParam(value = "shipmentName", defaultValue = "") String shipmentName,
                                     HttpServletRequest request) {
        try {

            if (StrUtil.isNotBlank(warehouseCode)) {
                // 获取货主-仓库关联关系
                List<WarehouseShipment> warehouseShipments = iWarehouseShipmentService.list(new QueryWrapper<WarehouseShipment>()
                        .lambda()
                        .eq(WarehouseShipment::getWarehouseCode, warehouseCode));
                // 获取所有货主缓存
                List<PartyCacheDO> parties = partyCache.getListByType(PartyTypeEnum.SHIPMENT.getValue());
                parties.addAll(partyCache.getListByType(PartyTypeEnum.SHIPMENT_COMPANY.getValue()));
                // 获取关联的code集合
                Map<String, Object> shipmentCodeMap;
                shipmentCodeMap = new HashMap<>();
                warehouseShipments.forEach(e -> shipmentCodeMap.put(e.getShipmentCode(), 1));
                // 根据集合过滤
                parties = parties.stream().filter(e -> shipmentCodeMap.containsKey(e.getCode())).collect(Collectors.toList());
                // 根据名称过滤
                if (StrUtil.isNotBlank(shipmentName)) {
                    parties = parties.stream().filter(e -> e.getName().contains(shipmentName)).collect(Collectors.toList());
                }

                return Result.ok().data(parties);
            }
            return Result.ok();
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }


    /**
     * WMS业务操作获取仓库数据
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "WMS业务操作根据仓库获取授权的绑定货主数据", notes = "仅限WMS业务操作页面下拉框使用。比如：" +
            "入库管理、出库管理中的列表、表单等页面使用，返回选择的仓库授权的货主信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer ")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = WarehouseVO.class))
    @NeedLogin
    @GetMapping("/business/shipments")
    public Result businessChooseData(
            HttpServletRequest request) {
        //校验授权仓库code和货主code不能为空
        Map<String, List<String>> authMap =  ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
        List<String> shipmentCodes = authMap.get(CommonConst.SHIPMENT_CODES);
        List<Shipment> shipmentList = iShipmentService.list(new LambdaQueryWrapper<Shipment>()
                .in(Shipment::getPartyCode,shipmentCodes)
        );
        List<Map<String, Object>> shipments = shipmentList.stream().map(BeanUtil::beanToMap).collect(Collectors.toList());
        return Result.ok().data(shipments);
    }

    /**
     * WMS业务操作获取仓库数据
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "WMS业务操作根据仓库获取授权的绑定货主数据", notes = "仅限WMS业务操作页面下拉框使用。比如：" +
            "基础信息页面使用，返回货主信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer ")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = WarehouseVO.class))
    @NeedLogin
    @GetMapping("/business/shipmentsWithoutAuthor")
    public Result businessChooseDataWithoutAuthor(
            HttpServletRequest request) {
        try {
            List<Shipment> shipmentList = iShipmentService.list(new LambdaQueryWrapper<Shipment>()
                    .eq(Shipment::getDeleted, NumConst.NUM_ZERO)
            );
            List<Map<String, Object>> shipments = shipmentList.stream().map(BeanUtil::beanToMap).collect(Collectors.toList());
            return Result.ok().data(shipments);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * WMS业务操作获取仓库数据
     *
     * @return
     */
    @ApiOperation(value = "WMS业务操作根据仓库获取授权的绑定货主数据", notes = "仅限WMS业务操作页面下拉框使用。比如：" +
            "入库管理、出库管理中的列表、表单等页面使用，返回选择的仓库授权的货主信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer ")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = WarehouseVO.class))
    @NeedLogin
    @GetMapping("/business/shipmentsWithUnitAndInventoryStatus")
    public Result businessChooseData() {
        try {
            //校验授权仓库code和货主code不能为空
             Map<String, List<String>> authMap = ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
            List<WarehouseCollection> warehouseVOList = new ArrayList<>();
            List<String> shipmentCodes = authMap.get(CommonConst.SHIPMENT_CODES);
            for (String shipmentCode : shipmentCodes) {
                WarehouseCollection warehouseCollection = new WarehouseCollection();
                warehouseCollection.setGoodsUnitList(goodsUnitService.findUnitByShipmentCode(shipmentCode));
                List<InventoryStatus> inventoryStatusList = inventoryStatusService.list(new QueryWrapper<InventoryStatus>().lambda()
                        .eq(InventoryStatus::getDeleted, "0").eq(InventoryStatus::getStatus, StatusEnum.ACTIVE.getValue())
                        .eq(InventoryStatus::getShipmentCode, shipmentCode));
                warehouseCollection.setInventoryStatusList(inventoryStatusList);
                warehouseCollection.setShipmentName(shipmentCache.translate(shipmentCode));
                warehouseCollection.setPartyCode(shipmentCode);
                warehouseVOList.add(warehouseCollection);
            }
/*
            assert shipmentCodes != null;
            List<Map<String, Object>> shipments = shipmentCodes.stream().map(s -> shipmentCache.get(s)).collect(Collectors.toList());
*/
            return Result.ok().data(warehouseVOList);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }


}
